package cn.ilikes.tools.hbase.jpa.clazzes.resources;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;

import org.slf4j.Logger;

import cn.ilikes.tools.hbase.jpa.clazzes.resources.ResourcesloadListener.ResourcesType;
import cn.ilikes.tools.logs.Loggerfactory;

public class Resources {

	private static Logger logger = Loggerfactory.instance(Resources.class);

	protected List<String> classes = new ArrayList<String>();

	private List<ResourcesloadListener> resourcesloadListeneres = new ArrayList<ResourcesloadListener>();

	public void addResourcesloadListener(ResourcesloadListener resourcesloadListener) {
		resourcesloadListeneres.add(resourcesloadListener);
	}

	public void loadJar(String jarFile) {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.info(logger, "load jar file :  " + jarFile);
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(jarFile);
			loadJar(fis);
		} catch (IOException e) {
			throw new ClasspathResourcesException(e);
		} finally {
			if (fis != null)
				try {
					fis.close();
				} catch (IOException e) {
					throw new ClasspathResourcesException(e);
				}
		}
	}

	/**
	 * Reads the jar file from a specified URL
	 * 
	 * @param url
	 */
	public void loadJar(URL url) {
		if (Loggerfactory.isdebug(logger))
			Loggerfactory.info(logger, "load url :  " + url.toString());

		InputStream in = null;
		try {
			in = url.openStream();
			loadJar(in);
		} catch (IOException e) {
			throw new ClasspathResourcesException(e);
		} finally {
			if (in != null)
				try {
					in.close();
				} catch (IOException e) {
					throw new ClasspathResourcesException(e);
				}
		}
	}

	/**
	 * Load the jar contents from InputStream
	 * 
	 */
	public void loadJar(InputStream jarStream) {

		BufferedInputStream bis = null;
		JarInputStream jis = null;

		try {
			bis = new BufferedInputStream(jarStream);
			jis = new JarInputStream(bis);

			JarEntry jarEntry = null;
			while ((jarEntry = jis.getNextJarEntry()) != null) {

				if (jarEntry.isDirectory()) {
					continue;
				}
				saveEntry(jarEntry.getName());
			}
		} catch (IOException e) {
			throw new ClasspathResourcesException(e);
		} catch (NullPointerException e) {
			Loggerfactory.info(logger, "Done loading.");

		} finally {
			if (jis != null)
				try {
					jis.close();
				} catch (IOException e) {
					throw new ClasspathResourcesException(e);
				}

			if (bis != null)
				try {
					bis.close();
				} catch (IOException e) {
					throw new ClasspathResourcesException(e);
				}
		}
	}

	/**
	 * For debugging
	 * 
	 * @param je
	 * @return String
	 */
	private String dump(JarEntry je) {
		StringBuffer sb = new StringBuffer();
		if (je.isDirectory()) {
			sb.append("d ");
		} else {
			sb.append("f ");
		}

		if (je.getMethod() == JarEntry.STORED) {
			sb.append("stored   ");
		} else {
			sb.append("defalted ");
		}

		sb.append(je.getName());
		sb.append("\t");
		sb.append("" + je.getSize());
		if (je.getMethod() == JarEntry.DEFLATED) {
			sb.append("/" + je.getCompressedSize());
		}

		return (sb.toString());
	}

	protected void saveEntry(String name) {
		name = name.replace("/", ".");
		//if (Loggerfactory.isdebug(logger))Loggerfactory.debug(logger, " save  entrty : " + name);
		if (name.endsWith(".class")) {
			for (ResourcesloadListener resourcesloadListener : resourcesloadListeneres) {
				resourcesloadListener.loadResources(name, ResourcesType.classes);
			}
		} else {
			for (ResourcesloadListener resourcesloadListener : resourcesloadListeneres) {
				resourcesloadListener.loadResources(name, ResourcesType.no_classes);
			}
		}
	}
}
